package v.show.health.server.configure;

import de.codecentric.boot.admin.server.domain.entities.Instance;
import de.codecentric.boot.admin.server.domain.entities.InstanceRepository;
import de.codecentric.boot.admin.server.domain.events.InstanceEvent;
import de.codecentric.boot.admin.server.notify.AbstractStatusChangeNotifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono;
import v.show.commons.notify.NotifyHelper;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author whz
 */
@Slf4j
public class AlertNotifier extends AbstractStatusChangeNotifier {

    private static final String DEFAULT_MESSAGE = "*#{instance.registration.name}* (#{instance.id}) is *#{event.statusInfo.status}*";

    private final Expression message;

    private final String env;

    public AlertNotifier(InstanceRepository repository, String env) {
        super(repository);
        this.env = env;
        this.message = new SpelExpressionParser()
                .parseExpression(DEFAULT_MESSAGE, ParserContext.TEMPLATE_EXPRESSION);
    }

    @Override
    @NonNull
    protected Mono<Void> doNotify(@NonNull InstanceEvent event, @NonNull Instance instance) {
        // 告警
        return Mono.fromRunnable(
                () -> {
                    String format = String.format("[%s]<%s>][%s]: %s", env, "-", now(), createContent(event, instance));
                    log.info(format);
                    NotifyHelper.defaultNotifyAtAll(format);
                }).doOnError(exception -> {
            log.error("", exception);
        }).then();
    }

    private String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    protected String createContent(InstanceEvent event, Instance instance) {
        Map<String, Object> root = new HashMap<>(3);
        root.put("event", event);
        root.put("instance", instance);
        root.put("lastStatus", getLastStatus(event.getInstance()));
        StandardEvaluationContext context = new StandardEvaluationContext(root);
        context.addPropertyAccessor(new MapAccessor());
        return message.getValue(context, String.class);
    }
}